home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / amiga_src / util.c < prev    next >
C/C++ Source or Header  |  2001-06-23  |  10KB  |  580 lines

  1. /*
  2.  * Copyright 1993, 1994, 1995, 1999, 2000 by Paul Mattes.
  3.  * Parts Copyright 1990 by Jeff Sparkes.
  4.  *  Permission to use, copy, modify, and distribute this software and its
  5.  *  documentation for any purpose and without fee is hereby granted,
  6.  *  provided that the above copyright notice appear in all copies and that
  7.  *  both that copyright notice and this permission notice appear in
  8.  *  supporting documentation.
  9.  */
  10.  
  11. /*
  12.  *    util.c
  13.  *        Utility functions for x3270
  14.  */
  15.  
  16. #include "globals.h"
  17. #include <pwd.h>
  18. #include <stdarg.h>
  19. #include "resources.h"
  20.  
  21. #include "utilc.h"
  22.  
  23. /*
  24.  * Cheesy internal version of sprintf that allocates its own memory.
  25.  */
  26. static char *
  27. xs_vsprintf(const char *fmt, va_list args)
  28. {
  29.     char *r;
  30. #if defined(HAVE_VASPRINTF) /*[*/
  31.     (void) vasprintf(&r, fmt, args);
  32.     if (r == CN)
  33.         Error("Out of memory");
  34.     return r;
  35. #else /*][*/
  36.     char buf[16384];
  37.     int nc;
  38.  
  39.     nc = vsprintf(buf, fmt, args);
  40.     if (nc > sizeof(buf))
  41.         Error("Internal buffer overflow");
  42.     r = Malloc(nc + 1);
  43.     return strcpy(r, buf);
  44. #endif /*]*/
  45. }
  46.  
  47. /*
  48.  * Common helper functions to insert strings, through a template, into a new
  49.  * buffer.
  50.  * 'format' is assumed to be a printf format string with '%s's in it.
  51.  */
  52. char *
  53. xs_buffer(const char *fmt, ...)
  54. {
  55.     va_list args;
  56.     char *r;
  57.  
  58.     va_start(args, fmt);
  59.     r = xs_vsprintf(fmt, args);
  60.     va_end(args);
  61.     return r;
  62. }
  63.  
  64. /* Common uses of xs_buffer. */
  65. void
  66. xs_warning(const char *fmt, ...)
  67. {
  68.     va_list args;
  69.     char *r;
  70.  
  71.     va_start(args, fmt);
  72.     r = xs_vsprintf(fmt, args);
  73.     va_end(args);
  74.     Warning(r);
  75.     Free(r);
  76. }
  77.  
  78. void
  79. xs_error(const char *fmt, ...)
  80. {
  81.     va_list args;
  82.     char *r;
  83.  
  84.     va_start(args, fmt);
  85.     r = xs_vsprintf(fmt, args);
  86.     va_end(args);
  87.     Error(r);
  88.     Free(r);
  89. }
  90.  
  91. /* Prettyprinter for strings with unprintable data. */
  92. void
  93. fcatv(FILE *f, char *s)
  94. {
  95.     char c;
  96.  
  97.     while ((c = *s++)) {
  98.         switch (c) {
  99.             case '\n':
  100.             (void) fprintf(f, "\\n");
  101.             break;
  102.             case '\t':
  103.             (void) fprintf(f, "\\t");
  104.             break;
  105.             case '\b':
  106.             (void) fprintf(f, "\\b");
  107.             break;
  108.             default:
  109.             if ((c & 0x7f) < ' ')
  110.                 (void) fprintf(f, "\\%03o", c & 0xff);
  111.             else
  112.                 fputc(c, f);
  113.             break;
  114.         }
  115.     }
  116. }
  117.  
  118. /*
  119.  * Definition resource splitter, for resources of the repeating form:
  120.  *    left: right\n
  121.  *
  122.  * Can be called iteratively to parse a list.
  123.  * Returns 1 for success, 0 for EOF, -1 for error.
  124.  *
  125.  * Note: Modifies the input string.
  126.  */
  127. int
  128. split_dresource(char **st, char **left, char **right)
  129. {
  130.     char *s = *st;
  131.     char *t;
  132.     Boolean quote;
  133.  
  134.     /* Skip leading white space. */
  135.     while (isspace(*s))
  136.         s++;
  137.  
  138.     /* If nothing left, EOF. */
  139.     if (!*s)
  140.         return 0;
  141.  
  142.     /* There must be a left-hand side. */
  143.     if (*s == ':')
  144.         return -1;
  145.  
  146.     /* Scan until an unquoted colon is found. */
  147.     *left = s;
  148.     for (; *s && *s != ':' && *s != '\n'; s++)
  149.         if (*s == '\\' && *(s+1) == ':')
  150.             s++;
  151.     if (*s != ':')
  152.         return -1;
  153.  
  154.     /* Stip white space before the colon. */
  155.     for (t = s-1; isspace(*t); t--)
  156.         *t = '\0';
  157.  
  158.     /* Terminate the left-hand side. */
  159.     *(s++) = '\0';
  160.  
  161.     /* Skip white space after the colon. */
  162.     while (*s != '\n' && isspace(*s))
  163.         s++;
  164.  
  165.     /* There must be a right-hand side. */
  166.     if (!*s || *s == '\n')
  167.         return -1;
  168.  
  169.     /* Scan until an unquoted newline is found. */
  170.     *right = s;
  171.     quote = False;
  172.     for (; *s; s++) {
  173.         if (*s == '\\' && *(s+1) == '"')
  174.             s++;
  175.         else if (*s == '"')
  176.             quote = !quote;
  177.         else if (!quote && *s == '\n')
  178.             break;
  179.     }
  180.  
  181.     /* Strip white space before the newline. */
  182.     if (*s) {
  183.         t = s;
  184.         *st = s+1;
  185.     } else {
  186.         t = s-1;
  187.         *st = s;
  188.     }
  189.     while (isspace(*t))
  190.         *t-- = '\0';
  191.  
  192.     /* Done. */
  193.     return 1;
  194. }
  195.  
  196. #if defined(X3270_DISPLAY) /*[*/
  197. /*
  198.  * List resource splitter, for lists of elements speparated by newlines.
  199.  *
  200.  * Can be called iteratively.
  201.  * Returns 1 for success, 0 for EOF, -1 for error.
  202.  */
  203. int
  204. split_lresource(char **st, char **value)
  205. {
  206.     char *s = *st;
  207.     char *t;
  208.     Boolean quote;
  209.  
  210.     /* Skip leading white space. */
  211.     while (isspace(*s))
  212.         s++;
  213.  
  214.     /* If nothing left, EOF. */
  215.     if (!*s)
  216.         return 0;
  217.  
  218.     /* Save starting point. */
  219.     *value = s;
  220.  
  221.     /* Scan until an unquoted newline is found. */
  222.     quote = False;
  223.     for (; *s; s++) {
  224.         if (*s == '\\' && *(s+1) == '"')
  225.             s++;
  226.         else if (*s == '"')
  227.             quote = !quote;
  228.         else if (!quote && *s == '\n')
  229.             break;
  230.     }
  231.  
  232.     /* Strip white space before the newline. */
  233.     if (*s) {
  234.         t = s;
  235.         *st = s+1;
  236.     } else {
  237.         t = s-1;
  238.         *st = s;
  239.     }
  240.     while (isspace(*t))
  241.         *t-- = '\0';
  242.  
  243.     /* Done. */
  244.     return 1;
  245. }
  246. #endif /*]*/
  247.  
  248. const char *
  249. get_message(const char *key)
  250. {
  251.     static char namebuf[128];
  252.     char *r;
  253.  
  254.     (void) sprintf(namebuf, "%s.%s", ResMessage, key);
  255.     if ((r = get_resource(namebuf)) != CN)
  256.         return r;
  257.     else {
  258.         (void) sprintf(namebuf, "[missing \"%s\" message]", key);
  259.         return namebuf;
  260.     }
  261. }
  262.  
  263. #define ex_getenv getenv
  264.  
  265. /* Variable and tilde substitution functions. */
  266. static char *
  267. var_subst(const char *s)
  268. {
  269.     enum { VS_BASE, VS_QUOTE, VS_DOLLAR, VS_BRACE, VS_VN, VS_VNB, VS_EOF }
  270.         state = VS_BASE;
  271.     char c;
  272.     int o_len = strlen(s) + 1;
  273.     char *ob;
  274.     char *o;
  275.     const char *vn_start = CN;
  276.  
  277.     if (strchr(s, '$') == CN)
  278.         return NewString(s);
  279.  
  280.     o_len = strlen(s) + 1;
  281.     ob = Malloc(o_len);
  282.     o = ob;
  283. #    define LBR    '{'
  284. #    define RBR    '}'
  285.  
  286.     while (state != VS_EOF) {
  287.         c = *s;
  288.         switch (state) {
  289.             case VS_BASE:
  290.             if (c == '\\')
  291.                 state = VS_QUOTE;
  292.             else if (c == '$')
  293.                 state = VS_DOLLAR;
  294.             else
  295.                 *o++ = c;
  296.             break;
  297.             case VS_QUOTE:
  298.             if (c == '$') {
  299.                 *o++ = c;
  300.                 o_len--;
  301.             } else {
  302.                 *o++ = '\\';
  303.                 *o++ = c;
  304.             }
  305.             state = VS_BASE;
  306.             break;
  307.             case VS_DOLLAR:
  308.             if (c == LBR)
  309.                 state = VS_BRACE;
  310.             else if (isalpha(c) || c == '_') {
  311.                 vn_start = s;
  312.                 state = VS_VN;
  313.             } else {
  314.                 *o++ = '$';
  315.                 *o++ = c;
  316.                 state = VS_BASE;
  317.             }
  318.             break;
  319.             case VS_BRACE:
  320.             if (isalpha(c) || c == '_') {
  321.                 vn_start = s;
  322.                 state = VS_VNB;
  323.             } else {
  324.                 *o++ = '$';
  325.                 *o++ = LBR;
  326.                 *o++ = c;
  327.                 state = VS_BASE;
  328.             }
  329.             break;
  330.             case VS_VN:
  331.             case VS_VNB:
  332.             if (!(isalnum(c) || c == '_')) {
  333.                 int vn_len;
  334.                 char *vn;
  335.                 char *vv;
  336.  
  337.                 vn_len = s - vn_start;
  338.                 if (state == VS_VNB && c != RBR) {
  339.                     *o++ = '$';
  340.                     *o++ = LBR;
  341.                     (void) strncpy(o, vn_start, vn_len);
  342.                     o += vn_len;
  343.                     state = VS_BASE;
  344.                     continue;    /* rescan */
  345.                 }
  346.                 vn = Malloc(vn_len + 1);
  347.                 (void) strncpy(vn, vn_start, vn_len);
  348.                 vn[vn_len] = '\0';
  349.                 if ((vv = ex_getenv(vn))) {
  350.                     *o = '\0';
  351.                     o_len = o_len
  352.                         - 1            /* '$' */
  353.                         - (state == VS_VNB)    /* { */
  354.                         - vn_len        /* name */
  355.                         - (state == VS_VNB)    /* } */
  356.                         + strlen(vv);
  357.                     ob = Realloc(ob, o_len);
  358.                     o = strchr(ob, '\0');
  359.                     (void) strcpy(o, vv);
  360.                     o += strlen(vv);
  361.                 }
  362.                 Free(vn);
  363.                 if (state == VS_VNB) {
  364.                     state = VS_BASE;
  365.                     break;
  366.                 } else {
  367.                     /* Rescan this character */
  368.                     state = VS_BASE;
  369.                     continue;
  370.                 }
  371.             }
  372.             break;
  373.             case VS_EOF:
  374.             break;
  375.         }
  376.         s++;
  377.         if (c == '\0')
  378.             state = VS_EOF;
  379.     }
  380.     return ob;
  381. }
  382.  
  383. /*
  384.  * Do tilde (home directory) substitution on a string.  Returns a malloc'd
  385.  * result.
  386.  */
  387. static char *
  388. tilde_subst(const char *s)
  389. {
  390.     char *slash;
  391.     const char *name;
  392.     const char *rest;
  393.     struct passwd *p;
  394.     char *r;
  395.     char *mname = CN;
  396.  
  397.     /* Does it start with a "~"? */
  398.     if (*s != '~')
  399.         return NewString(s);
  400.  
  401.     /* Terminate with "/". */
  402.     slash = strchr(s, '/');
  403.     if (slash) {
  404.         int len = slash - s;
  405.  
  406.         mname = Malloc(len + 1);
  407.         (void) strncpy(mname, s, len);
  408.         mname[len] = '\0';
  409.         name = mname;
  410.         rest = slash;
  411.     } else {
  412.         name = s;
  413.         rest = strchr(name, '\0');
  414.     }
  415.  
  416.     /* Look it up. */
  417. #ifndef AMIGA
  418.     if (!strcmp(name, "~"))    /* this user */
  419.         p = getpwuid(getuid());
  420.     else            /* somebody else */
  421.         p = getpwnam(name + 1);
  422. #else
  423. p=NULL;
  424. #endif
  425.  
  426.     /* Free any temporary copy. */
  427.     if (mname != CN)
  428.         Free(mname);
  429.  
  430.     /* Substitute and return. */
  431.     if (p == (struct passwd *)NULL)
  432.         r = NewString(s);
  433.     else {
  434.         r = Malloc(strlen(p->pw_dir) + strlen(rest) + 1);
  435.         (void) strcpy(r, p->pw_dir);
  436.         (void) strcat(r, rest);
  437.     }
  438.     return r;
  439. }
  440.  
  441. char *
  442. do_subst(const char *s, Boolean do_vars, Boolean do_tilde)
  443. {
  444.     if (!do_vars && !do_tilde)
  445.         return NewString(s);
  446.  
  447.     if (do_vars) {
  448.         char *t;
  449.  
  450.         t = var_subst(s);
  451.         if (do_tilde) {
  452.             char *u;
  453.  
  454.             u = tilde_subst(t);
  455.             Free(t);
  456.             return u;
  457.         }
  458.         return t;
  459.     }
  460.  
  461.     return tilde_subst(s);
  462. }
  463.  
  464. /*
  465.  * ctl_see
  466.  *    Expands a character in the manner of "cat -v".
  467.  */
  468. char *
  469. ctl_see(int c)
  470. {
  471.     static char    buf[64];
  472.     char    *p = buf;
  473.  
  474.     c &= 0xff;
  475.     if ((c & 0x80) && (c < 0xa0)) {
  476.         *p++ = 'M';
  477.         *p++ = '-';
  478.         c &= 0x7f;
  479.     }
  480.     if (c >= ' ' && c != 0x7f) {
  481.         *p++ = c;
  482.     } else {
  483.         *p++ = '^';
  484.         if (c == 0x7f) {
  485.             *p++ = '?';
  486.         } else {
  487.             *p++ = c + '@';
  488.         }
  489.     }
  490.     *p = '\0';
  491.     return buf;
  492. }
  493.  
  494. #if defined(X3270_DISPLAY) /*[*/
  495.  
  496. /* Glue between x3270 and the X libraries. */
  497.  
  498. /*
  499.  * A way to work around problems with Xt resources.  It seems to be impossible
  500.  * to get arbitrarily named resources.  Someday this should be hacked to
  501.  * add classes too.
  502.  */
  503. char *
  504. get_resource(const char *name)
  505. {
  506.     XrmValue value;
  507.     char *type;
  508.     char *str;
  509.     char *r = CN;
  510.  
  511.     str = xs_buffer("%s.%s", XtName(toplevel), name);
  512.     if ((XrmGetResource(rdb, str, 0, &type, &value) == True) && *value.addr)
  513.         r = value.addr;
  514.     XtFree(str);
  515.     return r;
  516. }
  517.  
  518. /*
  519.  * Input callbacks.
  520.  */
  521. typedef void voidfn(void);
  522. static void
  523. io_fn(XtPointer closure, int *source unused, XtInputId *id unused)
  524. {
  525.     voidfn *fn = (voidfn *)closure;
  526.  
  527.     (*fn)();
  528. }
  529.  
  530. unsigned long
  531. AddInput(int sock, voidfn *fn)
  532. {
  533.     return XtAppAddInput(appcontext, sock, (XtPointer) XtInputReadMask,
  534.         io_fn, (XtPointer)fn);
  535. }
  536.  
  537. unsigned long
  538. AddExcept(int sock, voidfn *fn)
  539. {
  540.     return XtAppAddInput(appcontext, sock, (XtPointer) XtInputExceptMask,
  541.         io_fn, (XtPointer)fn);
  542. }
  543.  
  544. void
  545. RemoveInput(unsigned long cookie)
  546. {
  547.     XtRemoveInput((XtInputId)cookie);
  548. }
  549.  
  550. /*
  551.  * Timer callbacks.
  552.  */
  553. static void
  554. to_fn(XtPointer closure, XtIntervalId *id)
  555. {
  556.     voidfn *fn = (voidfn *)closure;
  557.  
  558.     (*fn)();
  559. }
  560.  
  561. unsigned long
  562. AddTimeOut(unsigned long msec, voidfn *fn)
  563. {
  564.     return (unsigned long) XtAppAddTimeOut(appcontext, msec, to_fn,
  565.          (XtPointer)fn);
  566. }
  567.  
  568. void
  569. RemoveTimeOut(unsigned long cookie)
  570. {
  571.     XtRemoveTimeOut((XtIntervalId)cookie);
  572. }
  573.  
  574. KeySym
  575. StringToKeysym(char *s)
  576. {
  577.     return XStringToKeysym(s);
  578. }
  579. #endif /*]*/
  580.